/////precompiled////////
#include "precompiled.h"
////////////////////////


#include "frm_control_TRow.h"
#include "frm_control_TTable.h"
#include "frm_filler_TNodeSolidLine.h"

using namespace frm;
using namespace control;

// TRowCaption ////////////////////////////////////////////////////////////////

//
TRowCaption::TRowCaption(TRow &Row_) : TLine(Row_.GetWindow()),Row(Row_) 
{
}

//
void TRowCaption::TComponent_SelectEnter() { 
  TLine::TComponent_SelectEnter(); 
  Row.TRowCaption_SelectEnter();
}
void TRowCaption::TComponent_SelectExit() { 
  TLine::TComponent_SelectExit();  
  Row.TRowCaption_SelectExit();  
}

//
void TRowCaption::TComponent_KeyboardKey(grf::TKeyboardKey &KeyboardKey) {
  if (KeyboardKey.State == grf::TKeyboardKey::EState_Down) {
    if (KeyboardKey.Key == VK_RETURN) {
      TRow *Row = dynamic_cast<TRow*>(SearchThisOrParent(TRow::TType())); 
      
      if (Row) {
        if (Row->HasChildren()) {
          TBeginPaint P(this); 
            Row->UpdateExpand(!Row->GetExpand());
        }
        return;
      }
    }
  }
  TLine::TComponent_KeyboardKey(KeyboardKey);
}

//
void TRowCaption::TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles)
{ 
  TStyle *Style = dynamic_cast<TStyle*>(ParentStyles.SearchByEqualType(TStyle::TType())); if (Style) {
    SetStyle(*Style);
  }
  else {
    //TLine::TComponent_InheritStyleFrom(ParentStyles);
  }
}

// TRowChildrenIndent /////////////////////////////////////////////////////////

//
void TRowChildrenIndent::TStyle::SetFromParent(frm::TStyle *Parent_)
{
  if (!Parent_) {
    return;
  }

  TStyle *Parent = dynamic_cast<TStyle*>(Parent_);
  
  TPanel::TStyle::SetFromParent(Parent);
  Width = Parent->Width;
}

//
svl::TInfoParam TRowChildrenIndent::TStyle::AddInfoTo(svl::TInfoParam Info)
{
  return TPanel::TStyle::AddInfoTo(Info)
   .Add("Width",Width)
  ;
}

//
void TRowChildrenIndent::TStyle::SetDefault()
{
  Filler.Set(filler::TNodeSolidLine(grf::TColor(255,0,0)));
  Width = 20;
}

//
TRowChildrenIndent::TRowChildrenIndent(TRow &Row_) : TPanel(Row_.GetWindow()),Row(Row_)
{
  struct TStyle : public TRowChildrenIndent::TStyle
  {
    TStyle() { SetDefault(); }
  };
  static TStyle Style; SetStyle(Style);
}

//
TRowChildrenIndent &TRowChildrenIndent::SetStyle(TStyle &V)
{
  style = &V; 
  SetWidth(V.Width);
  TPanel::SetStyle(V); 
  return *this;
}

//
void TRowChildrenIndent::TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles)
{ 
  TStyle *Style = dynamic_cast<TStyle*>(ParentStyles.SearchByEqualType(TStyle::TType())); if (Style) {
    SetStyle(*Style);
  }
  else {
    //TPanel::TComponent_InheritStyleFrom(ParentStyles);
  }
}

// TRowChildren ///////////////////////////////////////////////////////////////

//
TRowChildren::TRowChildren(TRow &Row_) : TPanel(Row_.GetWindow()),Row(Row_)
{
}

//
void TRowChildren::DeleteChild(int N)
{
  BeginPaint();
  TPanel::DeleteChild(N); 
  
  if (!GetChildrenCount()) { 
    Row.ChildrenPanel->SetVisible(false);
  }
  EndPaint();
}

//
void TRowChildren::TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles)
{ 
  TStyle *Style = dynamic_cast<TStyle*>(ParentStyles.SearchByEqualType(TStyle::TType())); if (Style) {
    SetStyle(*Style);
  }
  else {
    //TPanel::TComponent_InheritStyleFrom(ParentStyles);
  }
}

// TRow ///////////////////////////////////////////////////////////////////////

//
void TRow::TStyle::SetFromParent(frm::TStyle *Parent_)
{
  if (!Parent_) {
    return;
  }

  TStyle *Parent = dynamic_cast<TStyle*>(Parent_);
  
  //frm::TStyle::SetFromParent(Parent);
  
  Normal  .SetFromParent(&Parent->Normal);
  Caption .SetFromParent(&Parent->Caption);
  Indent  .SetFromParent(&Parent->Indent);
  Children.SetFromParent(&Parent->Children);
}

//
svl::TInfoParam TRow::TStyle::AddInfoTo(svl::TInfoParam Info)
{
  return frm::TStyle::AddInfoTo(Info)
   .Add("Normal"  ,Normal)
   .Add("Caption" ,Caption)
   .Add("Indent"  ,Indent)
   .Add("Children",Children)
  ;
}

//
TRow::TRow(TWindow &Window) : TPanel(Window)//,Events(*this)
{
  Width_ChildrenMax().Height_ChildrenSum().DirectChildren_Vert()
   .WAlignChildren_Begin().HAlignChildren_Begin();

  AddChildLast(Caption = new TRowCaption(*this) ,true);
  Caption->Width_ChildrenSum().Height_ChildrenMax().DirectChildren_Horz()
   .WAlignChildren_Begin().HAlignChildren_Center();

  AddChildLast(ChildrenPanel = new TPanel(GetWindow()) ,true);
  ChildrenPanel->Width_ChildrenSum().Height_ChildrenMax().DirectChildren_Horz()
   .WAlignChildren_Begin().HAlignChildren_Begin();

    ChildrenPanel->AddChildLast(ChildrenIndent = new TRowChildrenIndent(*this) ,true);
    ChildrenIndent->Width_Fixed(20).Height_Parent().DirectChildren_Vert()
     .WAlignChildren_Begin().HAlignChildren_Begin();

    ChildrenPanel->AddChildLast(Children = new TRowChildren(*this) ,true);
    Children->Width_ChildrenMax().Height_ChildrenSum().DirectChildren_Vert()
     .WAlignChildren_Begin().HAlignChildren_Begin();
}

//
void TRow::BeforeDeleteRow() {
  TTable *Table = dynamic_cast<TTable*>(SearchParent(TTable::TType()));
  if (Table) {
    beforeDeleteRow(Caption,Table);
    beforeDeleteRow(Children,Table);
  }
}

//
void TRow::SetStyle(TStyle &V)
{
  TPanel::SetStyle(V.Normal);
  Caption->SetStyle(V.Caption);
  ChildrenIndent->SetStyle(V.Indent);
  Children->SetStyle(V.Children);
}

//
int TRow::CalcNumNodeLevel()
{
  int N = -1; TComponent *P = this; while (P) {
    if (dynamic_cast<TRow*>(P)) { 
      N++;
    }
    P = P->GetParent();
  }                 
  return N;
}

//
void TRow::UpdateExpand(bool V)
{
  if (GetExpand() != V && HasChildren()) {
    BeginPaint();
    
    bool Enable = true; if (V) { 
      //Events.Get().TEvents_BeforeExpand(TEvents::TBeforeExpand(Events,Enable));
    }
    else { 
      //Events.Get().TEvents_BeforeCollapse(TEvents::TBeforeCollapse(Events,Enable));
    }

    if (!Enable) { 
      return;
    }
    ChildrenPanel->UpdateVisible(V);

    if (V) { 
      //Events.Get().TEvents_AfterExpand(TEvents::TAfterExpand(Events));
    }
    else { 
      //Events.Get().TEvents_AfterCollapse(TEvents::TAfterCollapse(Events));
    }
      
    EndPaint();
  }
}

//
void TRow::ExpandAll()
{
  BeginPaint();
  UpdateExpand(true);
  
  for (int N = 0; N < Children->GetChildrenCount(); N++) {
    TRow *Child = dynamic_cast<TRow*>(&Children->GetChild(N)); if (Child) { 
      Child->ExpandAll();
    }
  }
  EndPaint();
}

//
void TRow::TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles)
{ 
  TStyle *Style = dynamic_cast<TStyle*>(ParentStyles.SearchByEqualType(TStyle::TType())); if (Style) {
    SetStyle(*Style);
  }
  else {
    //TPanel::TComponent_InheritStyleFrom(ParentStyles);
  }
}

//
void TRow::beforeDeleteRow(TPanel *Child,TTable *Table) {
  Child->TComponent_BeforeDeleteRow(Table);

  for (int N = 0; N < Child->GetChildrenCount(); N++) {
    TPanel *NextChild = static_cast<TPanel*>(&Child->GetChild(N));
    beforeDeleteRow(NextChild,Table);
  }
}

// TRowExpand /////////////////////////////////////////////////////////////////

//
void TRowExpand::TStyle::SetDefault()
{
  NoneChildren.Cursor.Set(cursor::TCursorWin(IDC_ARROW));
  NoneChildren.Filler.Set(filler::TColorLevelFrame(grf::TColor(0,255,0)));

  Collapse.Cursor.Set(cursor::TCursorWin(IDC_UPARROW));
  Collapse.Filler.Set(filler::TRoundRect(grf::TColor(255,255,255),grf::TColor(0,0,193)));

  Expand.Cursor.Set(cursor::TCursorWin(IDC_UPARROW));
  Expand.Filler.Set(filler::TRoundRect(grf::TColor(0,0,193),grf::TColor(255,255,255)));
}

//
void TRowExpand::TStyle::SetFromParent(frm::TStyle *Parent_)
{
  if (!Parent_) {
    return;
  }

  TStyle *Parent = dynamic_cast<TStyle*>(Parent_);
  
  NoneChildren.SetFromParent(&Parent->NoneChildren);
  Collapse.SetFromParent(&Parent->Collapse);
  Expand.SetFromParent(&Parent->Expand);
}

//
svl::TInfoParam TRowExpand::TStyle::AddInfoTo(svl::TInfoParam Info)
{
  return frm::TStyle::AddInfoTo(Info)
   .Add("NoneChildren",NoneChildren)
   .Add("Collapse",Collapse)
   .Add("Expand",Expand)
  ;
}

//
TRowExpand::TRowExpand(TWindow &Window) : TPanel(Window)
{
  SetRow(NULL);
  static TStyle Style; SetStyle(Style);

  SetRuleWidth (new geometry::TFixed(20));
  SetRuleHeight(new geometry::TFixed(20));
  SetRuleDirect(new geometry::THorz);
  SetRuleWAlign(new geometry::TCenter);
  SetRuleHAlign(new geometry::TCenter);
}

//
TRowExpand::TRowExpand(TRow &Row) : TPanel(Row.GetWindow())
{
  SetRow(&Row);
  static TStyle Style; SetStyle(Style);

  SetRuleWidth (new geometry::TFixed(20));
  SetRuleHeight(new geometry::TFixed(20));
  SetRuleDirect(new geometry::THorz);
  SetRuleWAlign(new geometry::TCenter);
  SetRuleHAlign(new geometry::TCenter);
}

//
TRowExpand &TRowExpand::SetStyle(TStyle &V)
{
  style = &V; 

  if (!row) {
    TPanel::SetStyle(V.NoneChildren);
    //Except("SetStyle[!row]");
    return *this;
  }
  
  if (row->HasChildren()) {
    if (row->GetExpand()) { 
      TPanel::SetStyle(V.Expand);
    }
    else { 
      TPanel::SetStyle(V.Collapse);
    }
  }
  else { 
    TPanel::SetStyle(V.NoneChildren);
  }

  return *this;
}

//
void TRowExpand::TComponent_Paint(TPaint &Paint,int NPaintStack)
{
  SetStyle(*style); TPanel::TComponent_Paint(Paint,NPaintStack);
}

//
void TRowExpand::TComponent_Mouse(TMouse Mouse)
{
  TPanel::TComponent_Mouse(Mouse); switch (Mouse.State)
  {
    case grf::TMouse::EState_LButtonDown:
    case grf::TMouse::EState_LButtonDblClick: {
      if (row) {
        row->UpdateExpand(!row->GetExpand());
      }
    }
    break;
  }
  SetStyle(*style);
}

//
void TRowExpand::TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles)
{ 
  TStyle *Style = dynamic_cast<TStyle*>(ParentStyles.SearchByEqualType(TStyle::TType())); if (Style) {
    SetStyle(*Style);
  }
  else {
    //TPanel::TComponent_InheritStyleFrom(ParentStyles);
  }
}
